package com.example.ota_ble.ble.ota.ble

import kotlin.experimental.xor

/**
 *          蓝牙OTA管理者
 *      开始，数据发送，结束等等
 * */

object ota_ble_manager {
    var TAG = "rocjan.ble_build_sendData"

    // 开始包
    fun send_ble_start_page(stat_page: ByteArray,pdu:Int,is_CompareVersion: Boolean)
    {
        stat_page[0] =   (OTA_BLE_PROCOL.CMD_OTA_START_EXT and 0xff ).toByte()
        stat_page[1] =   (OTA_BLE_PROCOL.CMD_OTA_START_EXT shr 8 and 0xff ).toByte()
        stat_page[2] =   (pdu and 0xff).toByte()
        stat_page[3] =   (if(is_CompareVersion==true) 0x01 else 0x00).toByte()
        stat_page.fill(0xff.toByte(), 4, stat_page.size)

    }
    /*
    *       构建升级数据
    **/
    fun set_ble_format(desc: ByteArray,src: ByteArray,page: Int)
    {
        desc[0] = (page and 0xff ).toByte()
        desc[1] = (page shr 8 and 0xff  ).toByte()
        //Log.i(TAG,"desc[0] = ${desc[0]},desc[1] = ${desc[1]}")
        src.copyInto(desc, 2)

        var crc: Int = crc16(desc,desc.size - 2)
        //Log.i(TAG,"crc = ${crc}")
        desc[desc.size - 2] = (crc  and 0xff ).toByte()
        desc[desc.size - 1] = (crc shr 8 and 0xff ).toByte()
        //Log.i(TAG, "desc after CRC update: ${desc.joinToString(", ")}")
    }
    // CRC32包
    fun send_ble_crc32_page(crc32_page: ByteArray)
    {
        var _crc32 = crc32.getCrc32()
        crc32_page[0] =    (_crc32 and 0xff ).toByte()
        crc32_page[1] =    (_crc32 shr 8 and 0xff ).toByte()
        crc32_page[2] =    (_crc32 shr 16 and 0xff ).toByte()
        crc32_page[3] =    (_crc32 shr 24 and 0xff ).toByte()
        crc32_page.fill(0xff.toByte(), 4, crc32_page.size)

    }
    // 结束包
    fun send_ble_end_page(end_page: ByteArray,Adr_index_max:Int)
    {
        end_page[0] =   (OTA_BLE_PROCOL.CMD_OTA_END and 0xff ).toByte()
        end_page[1] =   (OTA_BLE_PROCOL.CMD_OTA_END shr 8 and 0xff ).toByte()
        end_page[2] =   (Adr_index_max and 0xff ).toByte()
        end_page[3] =   (Adr_index_max shr 8 and 0xff ).toByte()
        end_page[4] =   (Adr_index_max.inv() and 0xff ).toByte()
        end_page[5] =   (Adr_index_max.inv() shr 8 and 0xff ).toByte()
        end_page.fill(0xff.toByte(), 6, end_page.size)

    }
    fun crc16(pD: ByteArray, len: Int): Int {
        val poly = intArrayOf(0, 0xA001)
        var crc = 0xFFFF
        var ds: Int
        var i: Int
        var j: Int

        j = len
        while (j > 0) {
            ds = pD[len - j].toInt()
            for (i in 0 until 8) {
                crc = (crc shr 1) xor poly[(crc xor ds) and 1]
                ds = ds shr 1
            }
            j--
        }

        return crc
    }



    object  crc32 {
        private var crc = 0xFFFFFFFF.toInt() // 初始 CRC 值

        // 半字节 CRC32 表
        private val fwCrc32HalfTbl = intArrayOf(
            0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
            0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
            0xedb88320.toInt(), 0xf00f9344.toInt(), 0xd6d6a3e8.toInt(), 0xcb61b38c.toInt(),
            0x9b64c2b0.toInt(), 0x86d3d2d4.toInt(), 0xa00ae278.toInt(), 0xbdbdf21c.toInt()
        )

        // 更新 CRC32 值
        fun update(data: ByteArray) {
            for (byte in data) {
                val unsignedByte = byte.toInt() and 0xFF // 处理 byte 为无符号

                // 处理高4位
                val high = (unsignedByte shr 4) and 0x0F
                val crcTop = (crc shr 28) and 0x0F
                val index = crcTop xor high
                crc = ((crc shl 4) and 0xFFFFFFFFF.toInt()) xor fwCrc32HalfTbl[index]

                // 处理低4位
                val low = unsignedByte and 0x0F
                val crcTopLow = (crc shr 28) and 0x0F
                val indexLow = crcTopLow xor low
                crc = ((crc shl 4) and 0xFFFFFFFF.toInt()) xor fwCrc32HalfTbl[indexLow]
            }
        }

        // 获取当前 CRC32 值
        fun getCrc32(): Int {
            return crc
        }

        // 重置 CRC32 值
        fun reset() {
            crc = 0xFFFFFFFF.toInt()
        }
    }


}